package com.wkck.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.wkck.VO.*;
import com.wkck.context.BaseContext;
import com.wkck.domain.*;
import com.wkck.dto.GetNoticeConditionsDto;
import com.wkck.exception.BaseException;
import com.wkck.exception.FileNotFoundException;
import com.wkck.exception.UploadErrorException;
import com.wkck.mapper.NoticeContentMapper;
import com.wkck.mapper.NoticeMapper;
import com.wkck.mapper.NoticePhotosMapper;
import com.wkck.service.NoticeService;
import com.wkck.utils.DateTimeGeneration;
import io.minio.MinioClient;
import io.minio.RemoveObjectArgs;
import io.minio.UploadObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.misc.resources.Messages_pt_BR;

import java.io.File;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

/**
 * @Author: CK
 * @Date: 2024/03/25/13:09
 * @Description:
 */
@Service
@Slf4j
public class NoticeServiceImpl extends ServiceImpl<NoticeMapper, Notice> implements NoticeService {

    @Autowired
    private NoticeMapper noticeMapper;

    @Autowired
    private NoticeContentMapper contentMapper;

    @Autowired
    private NoticePhotosMapper photosMapper;

    @Autowired
    private MinioClient minioClient;

    private static final String bucketPhotos = "notices";

    /***
     * @Author: CK
     * @Date: 2024/3/25
     * @Param: []
     * @Description: 创建通知
     */
    @Override
    @Transactional
    public CreateNoticeVo createNotice() {
        long noticeId = IdWorker.getId();

        Notice notice = Notice.builder()
                .id(noticeId)
                .yesapi_sys_notice_status(1)
                .create_by(BaseContext.getCurrentId().intValue())
                .create_time(DateTimeGeneration.now())
                .update_by(BaseContext.getCurrentId().intValue())
                .read_num(0)
                .build();
        noticeMapper.insert(notice);

        NoticeContent noticeContent = NoticeContent.builder().notice_id(noticeId).build();
        contentMapper.insert(noticeContent);

        return CreateNoticeVo.builder().id(noticeId).build();
    }

    /***
     * @Author: CK
     * @Date: 2024/3/25
     * @Param: [id]
     * @Description: 根据id获得通知信息
     */
    @Override
    public NoticeWithContentVo getNoticeAllById(Long id) {
        if (id == null) {
            throw new BaseException("编号为空 查询异常");
        }

        return noticeMapper.getNoticeAllById(id);
    }

    /***
     * @Author: CK
     * @Date: 2024/3/25
     * @Param: [notice]
     * @Description: 修改通知信息
     */
    @Override
    @Transactional
    public Boolean updateNotice(NoticeWithContentVo notice) {
        if (Objects.isNull(notice)) {
            throw new BaseException("通知信息为空 不允许编辑！");
        }

        if (notice.getNotice_title().length() < 2 || notice.getNotice_title().length() > 25) {
            throw new BaseException("通知标题长度不符合系统要求 不允许编辑！");
        }

        if (notice.getNotice_type() != 1 && notice.getNotice_type() != 2) {
            throw new BaseException("通知类型不符合系统要求 不允许编辑！");
        }

        if (notice.getYesapi_sys_notice_status() != 0 && notice.getYesapi_sys_notice_status() != 1) {
            throw new BaseException("通知状态不符合系统要求 不允许编辑！");
        }

        if (notice.getRemark() != null && notice.getRemark().length() > 200) {
            throw new BaseException("通知备注过长不符合系统要求 不允许编辑！");
        }

        if (Strings.isEmpty(notice.getContent())) {
            throw new BaseException("通知内容不允许为空！");
        }

        Notice noticeInfo = new Notice();
        BeanUtils.copyProperties(notice, noticeInfo);
        LambdaUpdateWrapper<Notice> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(Notice::getNotice_title, notice.getNotice_title())
                .set(Notice::getNotice_type, notice.getNotice_type())
                .set(Notice::getYesapi_sys_notice_status, notice.getYesapi_sys_notice_status())
                .set(Notice::getRemark, notice.getRemark())
                .eq(Notice::getId, notice.getId());
        noticeMapper.update(notice, updateWrapper);

        NoticeContent noticeContent = NoticeContent.builder()
                .notice_id(notice.getId())
                .content(notice.getContent())
                .build();
        LambdaUpdateWrapper<NoticeContent> contentLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        contentLambdaUpdateWrapper
                .set(NoticeContent::getContent, notice.getContent())
                .eq(NoticeContent::getNotice_id, notice.getId());

        contentMapper.update(noticeContent, contentLambdaUpdateWrapper);

        return true;
    }

    /***
     * @Author: CK
     * @Date: 2024/3/26
     * @Param: [dto]
     * @Description: 查询所有通知数据
     */
    @Override
    public PageResult getNotices(GetNoticeConditionsDto dto) {
        if (Objects.isNull(dto)) {
            throw new BaseException("参数异常 不允许查询");
        }

        PageHelper.startPage(dto.getCurrentPage(),dto.getSize());

        Page<NoticeListVo> page = noticeMapper.getNotices(dto);

        return PageResult.builder()
                .total(page.getTotal())
                .records(page.getResult())
                .build();
    }

    /***
     * @Author: CK
     * @Date: 2024/3/26
     * @Param: [ids]
     * @Description: 根据ids删除通知
     */
    @Override
    @Transactional
    public Boolean removeNoticesByIds(List<String> ids) {
        if (ids.isEmpty()) {
            throw new BaseException("编号为空 不允许操作!");
        }

        noticeMapper.deleteBatchIds(ids);

        LambdaQueryWrapper<NoticeContent> contentLambdaQueryWrapper = new LambdaQueryWrapper<>();
        contentLambdaQueryWrapper
                .in(NoticeContent::getNotice_id, ids);

        contentMapper.delete(contentLambdaQueryWrapper);

        LambdaQueryWrapper<NoticePhotos> photosLambdaQueryWrapper = new LambdaQueryWrapper<>();
        photosLambdaQueryWrapper
                .in(NoticePhotos::getNotice_id, ids);
        photosMapper.delete(photosLambdaQueryWrapper);

        List<NoticePhotos> newsPhotos = photosMapper.selectBatchIds(ids);
        for (NoticePhotos newsPhoto : newsPhotos) {
            try {
                minioClient.removeObject(
                        RemoveObjectArgs.builder()
                                .bucket(newsPhoto.getBucket())
                                .object(newsPhoto.getLocation())
                                .build()
                );
            } catch (Exception e) {
                throw new BaseException("minio文件删除失败");
            }
        }

        return true;
    }

    /****
     * @Author: CK
     * @Date: 2024/3/23
     * @Param: [notice]
     * @Description: 修改新闻状态
     */
    @Override
    public Boolean changeState(Notice notice) {
        if (Objects.isNull(notice)) {
            throw new BaseException("信息为空 修改失败!");
        }

        LambdaUpdateWrapper<Notice> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper
                .set(Notice::getYesapi_sys_notice_status, notice.getYesapi_sys_notice_status())
                .eq(Notice::getId, notice.getId());

        noticeMapper.update(notice, updateWrapper);

        return true;
    }

    /***
     * @Author: CK
     * @Date: 2024/3/23
     * @Param: [id]
     * @Description: 预览新闻
     */
    @Override
    public NoticeContent getPreviewNoticeContent(Long id) {
        if (id == null || String.valueOf(id).equals("undefined")) {
            throw new BaseException("编号为空 不允许预览");
        }

        LambdaQueryWrapper<NoticeContent> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper
                .eq(NoticeContent::getNotice_id, id);

        return contentMapper.selectOne(queryWrapper);
    }

    /***
     * @Author: CK
     * @Date: 2024/3/26
     * @Param: [file, id]
     * @Description: 上传正文中图片
     */
    @Override
    public UploadContentVo uploadContentPhoto(String localFilePath, long size, String filename, Long id) {
        File file = new File(localFilePath);

        if (!file.exists()) {
            throw new FileNotFoundException("文件未找到，上传失败!");
        }

        if (id == null) {
            throw new BaseException("编号为空 不允许添加正文图片!");
        }

        String location = id + "/content/" + UUID.randomUUID() + filename;

        try {
            minioClient.uploadObject(
                    UploadObjectArgs.builder()
                            .bucket(bucketPhotos)
                            .object(location)
                            .filename(localFilePath)
                            .build());
            log.info("正文图片上传成功, {}", location);
        } catch (Exception e) {
            throw new UploadErrorException("正文图片上传失败");
        }

        NoticePhotos photo = NoticePhotos.builder()
                .file_name(filename)
                .bucket(bucketPhotos)
                .size(String.valueOf(size))
                .location(location)
                .notice_id(id)
                .create_time(DateTimeGeneration.now())
                .create_user(BaseContext.getCurrentId().intValue())
                .build();

        photosMapper.insert(photo);

        return UploadContentVo.builder()
                .bucket(bucketPhotos)
                .file_name(filename)
                .url(location)
                .build();
    }
}
